
package com.zzy.demo.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.session.HttpSessionEventPublisher;

import com.zzy.demo.config.properties.SecurityProperties;
import com.zzy.demo.security.MyUserDetailsService;
import com.zzy.demo.security.authentication.MyAuthenticationFailureHandler;
import com.zzy.demo.security.authentication.MyAuthenticationSuccessHandler;
import com.zzy.demo.security.logout.MyLogoutSuccessHandler;
import com.zzy.demo.security.session.MyExpiredSessionStrategy;
import com.zzy.demo.utils.validate.code.ImageCodeFilter;


@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	
	
	/**
	 * 配置这个相当于               前端 加密的密码         和      数据库加密          都      必须用这个
	 * @return
	 */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
	
	@Autowired
	private DataSource dataSource;
	
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl  tokenRepository=new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        //第一次创建开启
        //tokenRepository.setCreateTableOnStartup(true); 
		return tokenRepository;
	}
	
	@Autowired
	MyUserDetailsService  myUserDetailsService;
	
	
	@Autowired
	SecurityProperties  securityProperties;
	
	@Autowired
	MyAuthenticationSuccessHandler  myAuthenticationSuccessHandler;
	
	@Autowired	
	MyAuthenticationFailureHandler  myAuthenticationFailureHandler;
	
	@Autowired	
	MyLogoutSuccessHandler  myLogoutSuccessHandler;
	

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
    	//自定义图片处理
    	ImageCodeFilter  imageCodeFilter=new ImageCodeFilter();
    	imageCodeFilter.setMyAuthenticationFailureHandler(myAuthenticationFailureHandler);
		   
		        http
		        .addFilterBefore(imageCodeFilter, UsernamePasswordAuthenticationFilter.class)
		        .formLogin()    //表单登录
		            .loginPage("/authentication/require")   //自定义登陆的页面
		            .loginProcessingUrl("/authentication/form")   //指定登陆action 的 url
		            .successHandler(myAuthenticationSuccessHandler)  //登录成功处理
		            .failureHandler(myAuthenticationFailureHandler)  //登出失败处理
		            .and()
		            .rememberMe()
		            .tokenRepository(persistentTokenRepository())
		            .tokenValiditySeconds(3600)
		            .userDetailsService(myUserDetailsService)
		            .and()
		            .sessionManagement()
		            .invalidSessionUrl("/session/invalid")
		            //并发只允许一个用户
		            .maximumSessions(1)
		            //并发处理策略
		            .expiredSessionStrategy(new MyExpiredSessionStrategy())
				    .and()
				    .and()
				    
				    .logout()
				    .logoutUrl("/logout")
				   // .logoutSuccessUrl("logout.html")
				    .logoutSuccessHandler(myLogoutSuccessHandler)
				    .deleteCookies("JSESSIONID")
				    
				    .and()
				    .authorizeRequests()  //请求认证模块   所有请求都需要认证     
				    .antMatchers("/authentication/require",
				    		"/logout",
				    		"/login",
				    		"/register/*",
				    		"/code/image").permitAll()  //登录页面不认证
					.anyRequest().authenticated()  //所有请求认证
					.and()
					.csrf().disable();  //跨站请求伪造
					
	}
	
    /**
     * session过期
     * @return
     */
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }


}
